<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>并发控制可视化</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #1a1a1a;
            color: #fff;
        }

        h1 {
            text-align: center;
            color: #4CAF50;
            font-size: 2.5em;
            margin-bottom: 30px;
            text-shadow: 0 0 10px rgba(76, 175, 80, 0.3);
        }

        .stats {
            display: flex;
            justify-content: space-around;
            margin: 20px 0;
            padding: 20px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
        }

        .stat-item {
            text-align: center;
        }

        .stat-value {
            font-size: 2em;
            font-weight: bold;
            color: #4CAF50;
            text-shadow: 0 0 10px rgba(76, 175, 80, 0.3);
        }

        .stat-label {
            color: #888;
            margin-top: 5px;
        }

        .task-container {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
            gap: 20px;
            margin-top: 30px;
        }

        .task-card {
            background: rgba(255, 255, 255, 0.05);
            padding: 20px;
            border-radius: 15px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
            transition: all 0.3s ease;
            transform: translateY(0);
            position: relative;
            overflow: hidden;
        }

        .task-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.05));
            pointer-events: none;
        }

        .task-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
        }

        .task-card.running {
            border: 2px solid #4CAF50;
            animation: pulse 2s infinite;
        }

        .task-card.completed {
            background: rgba(76, 175, 80, 0.1);
            border: 2px solid transparent;
        }

        .task-card h3 {
            color: #4CAF50;
            margin: 0 0 15px 0;
        }

        .progress-bar {
            width: 100%;
            height: 6px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 3px;
            overflow: hidden;
            margin: 15px 0;
        }

        .progress {
            height: 100%;
            background: linear-gradient(90deg, #4CAF50, #81C784);
            width: 0;
            transition: width 0.3s ease;
            box-shadow: 0 0 10px rgba(76, 175, 80, 0.5);
        }

        @keyframes pulse {
            0% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.4); }
            70% { box-shadow: 0 0 0 10px rgba(76, 175, 80, 0); }
            100% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0); }
        }

        .time-text {
            color: #888;
            font-size: 0.9em;
            margin: 10px 0 0 0;
        }

        /* 添加任务完成动画 */
        @keyframes complete {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }

        .task-card.completed {
            animation: complete 0.5s ease;
        }
    </style>
</head>
<body>
    <h1>并发任务执行可视化</h1>
    <div class="stats">
        <div class="stat-item">
            <div class="stat-value" id="currentParallel">0</div>
            <div class="stat-label">当前并发数</div>
        </div>
        <div class="stat-item">
            <div class="stat-value" id="remainingTasks">20</div>
            <div class="stat-label">剩余任务数</div>
        </div>
        <div class="stat-item">
            <div class="stat-value" id="completedTasks">0</div>
            <div class="stat-label">已完成任务</div>
        </div>
    </div>
    <div class="task-container" id="taskContainer"></div>

    <script>
// 生成任务卡片
const taskContainer = document.getElementById('taskContainer');
const longTasks = [];
const taskCards = [];

for (let i = 0; i < 20; i++) {
    // 创建任务卡片
    const card = document.createElement('div');
    card.className = 'task-card';
    card.innerHTML = `
        <h3>任务 ${i + 1}</h3>
        <div class="progress-bar">
            <div class="progress" id="progress-${i}"></div>
        </div>
        <p id="time-${i}">等待中...</p>
    `;
    taskContainer.appendChild(card);
    taskCards.push(card);

    // 创建任务
    longTasks.push(() => {
        return new Promise((resolve, reject) => {
            const randomTime = Math.floor(Math.random() * 2000) + 2000;
            const startTime = Date.now();

            card.className = 'task-card running';

            const progressBar = document.getElementById(`progress-${i}`);
            const timeText = document.getElementById(`time-${i}`);

            // 更新进度条
            const interval = setInterval(() => {
                const elapsed = Date.now() - startTime;
                const progress = Math.min((elapsed / randomTime) * 100, 100);
                progressBar.style.width = `${progress}%`;
                timeText.textContent = `执行中: ${elapsed}ms`;
            }, 50);

            setTimeout(() => {
                clearInterval(interval);
                card.className = 'task-card completed';
                timeText.textContent = `完成: ${randomTime}ms`;
                resolve(`第${i + 1}个任务，耗时${randomTime}ms`);
            }, randomTime);
        });
    });
}

function runTasks(tasks, parallelNum) {
    if (tasks === null || tasks.length === 0) return;

    const currentParallel = document.getElementById('currentParallel');
    const remainingTasks = document.getElementById('remainingTasks');
    const completedTasks = document.getElementById('completedTasks');
    let completed = 0;

    return new Promise((resolve, reject) => {
        let count = 0;
        function _circleRun() {
            while (tasks.length > 0) {
                if (count >= parallelNum) break;

                let task = tasks.shift();
                count++;

                currentParallel.textContent = count;
                remainingTasks.textContent = tasks.length;

                task().then(res => {
                    count--;
                    completed++;
                    completedTasks.textContent = completed;
                    currentParallel.textContent = count;

                    if (count < parallelNum) {
                        _circleRun();
                    }
                    if (count === 0 && tasks.length === 0) {
                        resolve();
                    }
                });
            }
        }
        _circleRun();
    });
}

runTasks(longTasks, 3).then(() => {
    console.log('所有任务执行完毕');
});
</script>
</body>
</html>
